package com.jwsoft.manager.core.integration.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.engine.assistant.core.utils.SessionUtil;
import com.bifang.engine.cache.redis.RedisHelper;
import com.bifang.engine.data.core.util.PagerUtil;
import com.bifang.module.base.common.vo.common.CommonVO;
import com.bifang.module.base.common.vo.excel.ExcelModelVO;
import com.bifang.module.base.common.vo.excel.ExcelVO;
import com.bifang.module.base.core.helper.DictHelper;
import com.bifang.module.base.core.helper.ExcelCommonHelper;
import com.bifang.module.base.core.integration.CommonIntegration;
import com.bifang.module.base.core.integration.ExcelIntegration;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.enums.EduStudentEnrollDictEnum;
import com.jwsoft.manager.common.vo.eduSjtj02.*;
import com.jwsoft.manager.core.dao.mapper.EduSjtj02Mapper;
import com.jwsoft.manager.core.dao.model.EduLivePlace;
import com.jwsoft.manager.core.dao.model.EduSjtj02;
import com.jwsoft.manager.core.dao.model.EduSocialSecurity;
import com.jwsoft.manager.core.dao.service.EduLivePlaceService;
import com.jwsoft.manager.core.dao.service.EduSjtj02Service;
import com.jwsoft.manager.core.dao.service.EduSocialSecurityService;
import com.jwsoft.manager.core.integration.EduSjtj02Integration;
import com.jwsoft.manager.core.util.EduHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 数据统计02业务实现类
 *
 * @author linyh
 * @since 2023-04-21
 */
@ApiService(funcCode = "eduSjtj02", title = "数据统计02")
public class EduSjtj02IntegrationImpl implements EduSjtj02Integration {

    @Autowired
    public EduSjtj02Service eduSjtj02Service;
    @Value("/data/upload")
    private String tempPath;
    @Autowired
    public ExcelIntegration excelIntegration;
    @Autowired
    private ExcelCommonHelper excelCommonHelper;
    @Autowired
    EduHelper eduHelper;
    @Autowired
    EduSjtj02Mapper mapper;
    @Autowired
    CommonIntegration commonIntegration;
    @Autowired
    EduSocialSecurityService eduSocialSecurityService;
    @Autowired
    EduLivePlaceService eduLivePlaceService;
    private final String saveSjtj02 = "task:saveSjtj02";
    @Autowired
    private RedisHelper redisHelper;
    @Autowired
    public DictHelper dictHelper;

    @Override
    @OpApi(funcCode = "eduSjtj020001", title = "数据统计02分页查询", funcType = FuncTypeEnum.query)
    public PageInfo<EduSjtj02VO> getList(EduSjtj02QueryVO vo) {
        if(ObjectUtils.isEmpty(vo.getYear())){
            vo.setYear(eduHelper.thisYear());
        }
        if(ObjectUtils.isEmpty(vo.getAreaCode())){
            CommonVO commonVO=new CommonVO();
            commonVO.setParamKey("area_code");
            String areaCode=commonIntegration.getValueByKey(commonVO);
            vo.setAreaCode(areaCode);
        }

        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(100);
        }
        PageHelper.startPage(vo.getPageNum(),vo.getPageSize());
        LambdaQueryWrapper<EduSjtj02> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EduSjtj02::getYear, vo.getYear());
        lambdaQueryWrapper.eq(EduSjtj02::getAreaCode, vo.getAreaCode()).eq(StringUtils.isNotBlank(vo.getSchoolId()),EduSjtj02::getSchoolId,vo.getSchoolId());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(vo.getSchoolCategory()),EduSjtj02::getSchoolCategory,vo.getSchoolCategory());
        List<EduSjtj02> list = eduSjtj02Service.list(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduSjtj02> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduSjtj02VO> resultList = Convert.toList(EduSjtj02VO.class, pageInfo.getList());
        resultList.forEach(item->{
            if(!ObjectUtils.isEmpty(item.getA())
                    && !ObjectUtils.isEmpty(item.getB())
                    && !ObjectUtils.isEmpty(item.getEnrolment())){
                double ab = item.getA().doubleValue()+item.getB().doubleValue();

                double jh = item.getEnrolment().doubleValue();
                if(jh>0){
                    DecimalFormat df44 = new DecimalFormat("#.00");
                    double abzb = Double.parseDouble(df44.format(ab/jh));
                    item.setAbzb(abzb);
                }

            }
        });
        // 转义数据字典值
        dictHelper.valueToName(resultList, Arrays.asList(EduStudentEnrollDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "eduSjtj020002", title = "数据统计02根据主键查询详情", funcType = FuncTypeEnum.query)
    public EduSjtj02VO getById(EduSjtj02KeyVO vo) {
        EduSjtj02 entity = eduSjtj02Service.getById(vo.getEdusjtj02Id());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduSjtj02VO result = Convert.convert(EduSjtj02VO.class, entity);
        return result;
    }
    /** 保存前统一校验*/
    @Override
    @OpApi(funcCode = "eduSjtj020003", title = "数据统计02保存前校验", funcType = FuncTypeEnum.other ,checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduSjtj02VO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验
    }

    @Override
    @OpApi(funcCode = "eduSjtj020004", title = "数据统计02新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "eduSjtj020004",
            operationName = "数据统计02新增",
            dataType = "edusjtj02Id",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSjtj02VO add(EduSjtj02VO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduSjtj02 entity = Convert.convert(EduSjtj02.class, vo);
        eduSjtj02Service.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setEdusjtj02Id(entity.getEdusjtj02Id());
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduSjtj020005", title = "数据统计02修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "eduSjtj020005",
            operationName = "数据统计02修改",
            dataType = "edusjtj02Id",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSjtj02VO edit(EduSjtj02VO vo) {
        if (ObjectUtils.isEmpty(vo.getEdusjtj02Id())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduSjtj02 oldEntity = eduSjtj02Service.getById(vo.getEdusjtj02Id());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduSjtj02 entity = Convert.convert(EduSjtj02.class, vo);
        eduSjtj02Service.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduSjtj020006", title = "数据统计02根据主键删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "eduSjtj020006",
            operationName = "数据统计02删除",
            dataType = "edusjtj02Id",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduSjtj02KeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getEdusjtj02Id())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduSjtj02 entity = eduSjtj02Service.getById(vo.getEdusjtj02Id());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduSjtj02Service.removeById(vo.getEdusjtj02Id());
    }

    @Override
    @OpApi(funcCode = "eduSjtj020007", title = "生成数据统计02表数据",
            funcType = FuncTypeEnum.insert,checkPrivilege = BoolEnum.FALSE,publicFlag =BoolEnum.TRUE)
    @SaveOplog(
            operationType = "eduSjtj020007",
            operationName = "生成数据统计02表数据",
            dataType = "edusjtj02Id",
            auType = AuTypeEnum.OTHER)
    @Async("commonTaskExecutor")
    public void saveEduSjtj02(EduSjtj02InVO vo) {
        if (redisHelper.hasKey(saveSjtj02)) {
            throw new AppException("正在批量生成预报名数据中...");
        }
        redisHelper.set(saveSjtj02, "1", 1000);
        try {
            if(ObjectUtils.isEmpty(vo.getYear())){
                vo.setYear(eduHelper.thisYear());
            }
            if(ObjectUtils.isEmpty(vo.getAreaCode())){
                vo.setAreaCode(SessionUtil.getAreaCode());
            }
            if (ObjectUtils.isEmpty(vo.getAreaCode())) {
                vo.setAreaCode(eduHelper.thisAreaCode());
            }
            //删除现有的
            //不保留原来的数据
            LambdaQueryWrapper<EduSjtj02> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(EduSjtj02::getYear, vo.getYear());
            lambdaQueryWrapper.eq(EduSjtj02::getAreaCode, vo.getAreaCode());
            Long list_del = eduSjtj02Service.count(lambdaQueryWrapper);
            if (list_del > 0) {
                if (vo.getYear() < eduHelper.thisYear()) {
                    throw new AppException("历史年度不能重新生成");
                }
                mapper.delete(lambdaQueryWrapper);
            }
            System.out.println("删除成功");
            //生成数据
            eduSjtj02Service.insertEduSjtj02(vo);//create table edu_bak_yc1_2023
            //判断上年度没有招生方案学校

            eduSjtj02Service.updatebmrs(vo);//上年度报名人数
            eduSjtj02Service.updatelqrs(vo);//上年度录取人数
            eduSjtj02Service.updatembrs(vo);//上年度民办录取人数
            eduSjtj02Service.updateA(vo);//A
            eduSjtj02Service.updateA1(vo);//A1
            eduSjtj02Service.updateB(vo);//B
            eduSjtj02Service.updateB1(vo);//B1
            eduSjtj02Service.updateC(vo);//C
            eduSjtj02Service.updateC1(vo);//C1
            eduSjtj02Service.updatehk(vo);//户口
            eduSjtj02Service.updateother(vo);//其他
            eduSjtj02Service.updateother_hj(vo);//其他户籍
            //--------------------------------------------------------------------------------
            //其他社保
            //其他居住证

            List<EduSjtj02GetSbJzzVO> getSbJzzList = eduSjtj02Service.getSbJzzList(vo);
            if(!CollectionUtils.isEmpty(getSbJzzList)){
                Map<String, Integer> sbMap = new HashMap<>();
                Map<String, Integer> jzzMap = new HashMap<>();
                for(EduSjtj02GetSbJzzVO sjvo:getSbJzzList){
                    List<String> idcardList = new ArrayList<>();
                    idcardList.add(sjvo.getIdcard());
                    if (StringUtils.isNotBlank(sjvo.getFatherIdcard())) {
                        idcardList.add(sjvo.getFatherIdcard());
                    }
                    if (StringUtils.isNotBlank(sjvo.getMotherIdcard())) {
                        idcardList.add(sjvo.getMotherIdcard());
                    }
                    String schoolId = sjvo.getSchoolId();
                    int cn_sb = 0;
                    int cn_jzz = 0;
                    if (sbMap.containsKey(schoolId)) {
                        cn_sb = sbMap.get(schoolId);
                    }
                    if (jzzMap.containsKey(schoolId)) {
                        cn_jzz = jzzMap.get(schoolId);
                    }
                    QueryWrapper<EduSocialSecurity> qw_fa = new QueryWrapper<>();
                    qw_fa.eq("del",0)
                            .in("aae140","110","120")
                            .in("aac147", idcardList)
                            .eq("aac008", "1")
                            .eq("aac031", "1")
                            .eq("Year", vo.getYear())
                            .eq("aab301",vo.getAreaCode());
                    if(eduSocialSecurityService.count(qw_fa)>=1){
                        cn_sb++;
                    }else{
                        QueryWrapper<EduLivePlace> qw_zzz = new QueryWrapper<>();
                        qw_zzz.eq("del",0)
                                .in("sfzh", idcardList)
                                .eq("year", vo.getYear())
                                .eq("area_code",vo.getAreaCode());
                        if(eduLivePlaceService.count(qw_zzz)>=1){
                            cn_jzz++;
                        }
                    }
                    sbMap.put(schoolId, cn_sb);
                    jzzMap.put(schoolId, cn_jzz);
                }
                LambdaQueryWrapper<EduSjtj02> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(EduSjtj02::getYear, vo.getYear()).eq(EduSjtj02::getAreaCode, vo.getAreaCode());
                List<EduSjtj02> list = eduSjtj02Service.list(queryWrapper);
                for (EduSjtj02 eduSjtj02 : list) {
                    boolean flag = false;
                    if (sbMap.containsKey(eduSjtj02.getSchoolId()) && sbMap.get(eduSjtj02.getSchoolId()) > 0) {
                        eduSjtj02.setOtherSb(new BigDecimal(sbMap.get(eduSjtj02.getSchoolId())));
                        flag = true;
                    }
                    if (jzzMap.containsKey(eduSjtj02.getSchoolId()) && jzzMap.get(eduSjtj02.getSchoolId()) > 0) {
                        eduSjtj02.setOtherJzz(new BigDecimal(jzzMap.get(eduSjtj02.getSchoolId())));
                        flag = true;
                    }
                    if (flag) {
                        eduSjtj02Service.updateById(eduSjtj02);
                    }

                }
            }

            //--------------------------------------------------------------------------------
            eduSjtj02Service.updatewy(vo);//weiyi
            eduSjtj02Service.updatewyhk(vo);//weiyihukou
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            redisHelper.del(saveSjtj02);

        }
        redisHelper.del(saveSjtj02);
    }

    @Override
    @OpApi(funcCode = "eduSjtj020008", title = "学校报名预测情况统计excel导出", funcType = FuncTypeEnum.other)
    public void downloadData(EduSjtj02QueryVO vo, HttpServletResponse response) {
        ExcelVO excelVO = new ExcelVO();
        excelVO.setModelCode("eduSjtj02");
        ExcelModelVO excelModelVO=excelIntegration.getModel(excelVO);

        if(ObjectUtils.isEmpty(vo.getYear())){
            vo.setYear(eduHelper.thisYear());
        }
        if(ObjectUtils.isEmpty(vo.getAreaCode())){
            CommonVO commonVO=new CommonVO();
            commonVO.setParamKey("area_code");
            String areaCode=commonIntegration.getValueByKey(commonVO);
            vo.setAreaCode(areaCode);
        }

        String destFilePath = this.tempPath + "/" + IdUtil.fastSimpleUUID() + "." + excelModelVO.getExcelType();
        int pageNum=1;
        setData(excelModelVO,null,destFilePath,vo,pageNum);
        String fileName="学校报名预测情况统计"+ DateUtil.today();
        if (StringUtils.isBlank(fileName)) {
            fileName =
                    excelModelVO.getModelName()
                            + "_"
                            + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN)
                            + "."
                            + (StringUtils.isBlank(excelModelVO.getExcelType())
                            ? "xls"
                            : excelModelVO.getExcelType());
        }
        File file = FileUtil.file(destFilePath);
        BufferedInputStream in = null;
        try {
            in = FileUtil.getInputStream(file);
            ServletUtil.write(response, in, "application/octet-stream;charset=utf-8", fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(in!=null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            FileUtil.del(destFilePath);
        }
    }

    private void setData(ExcelModelVO excelModelVO, ExcelWriter excelWriter, String destFilePath, EduSjtj02QueryVO vo, int pageNum){
        vo.setPageNum(pageNum);
        vo.setPageSize(100);
        boolean closeFlag = false;
        try {
            PageInfo<EduSjtj02VO> pageInfo= getList(vo);
            String total=String.valueOf(pageInfo.getTotal());
            List<Map<String,Object>> list=new ArrayList<>();
            if(!CollectionUtils.isEmpty(pageInfo.getList())){
                for(EduSjtj02VO sjtj02VO:pageInfo.getList()){
                    list.add(BeanUtil.beanToMap(sjtj02VO,false,true));
                }
            }
            if(pageNum==1){
                if(excelWriter==null){
                    excelWriter=excelCommonHelper.createExcelWriter(excelModelVO,destFilePath,Integer.parseInt(total));
                }
                excelCommonHelper.writeMap(excelWriter,list);
            }else{
                excelCommonHelper.writeMap(excelWriter,list);
            }
            if(pageInfo.isHasNextPage()){
                pageNum=pageNum+1;
                setData(excelModelVO,excelWriter,destFilePath,vo,pageNum);
            }else {
                closeFlag = true;
            }
        }catch (AppException appEx){
            throw appEx;
        }catch (Exception e){
            throw new AppException("调用自定义写入服务异常:" + e.getMessage());
        }finally {
            if(closeFlag&&excelWriter!=null){
                excelWriter.close();
            }
        }
    }
}
